<?php
include_once('dao_package.php');
include_once('dao_log.php');
include_once('dao_common.php');
include_once('dao_conv.php');

$soap_ns="xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ".
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ".
"xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" ".
"xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"";

/*
XML 错误Handle,因为DOM对象不会直接抛出异常，而是通过错误展示xml格式问题，所以必须实现错误handle
抛出DOMException异常
*/
function handle_xml_error($errno, $errstr, $errfile, $errline)
{
	if ($errno==E_WARNING && (substr_count($errstr,"DOMDocument::loadXML()")>0))
	{
		throw new DOMException($errstr);
	}
	else
	return false;
}


function check_special_char(&$xml)
{
	$chars=explode("\n",file_get_contents('sp_char.txt'));
	foreach($chars as $key=>$value)
	{
		if(strlen($value)==0)
		{
			continue;
		}
		$pare = explode('=',$value);
		$xml = dao_str_replace(trim($pare[0]),trim($pare[1]),$xml);
	}
}


//2007-8，由于php的dom只支持utf-8，所以xml部分必须转成utf-8处理，无奈
function  from_xml(&$pack,&$xml_text,&$msg=NULL)
{
	include_once("dao_bo_session.php");
	bo_session_set("reqxml",$xml_text);
	check_special_char(&$xml_text);
	// echo $xml_text;
	//*通过DOM对象获取根节点名称
	$xml_text = dao_str_replace("&nbsp;",' ',$xml_text);
	if(strpos($xml_text,"encoding=\"gb2312\"")===false&&strpos($xml_text,"encoding='gb2312'")===false)
	{
	}
	else
	{
		$xml_text = str_replace("encoding=\"gb2312\"","encoding=\"utf-8\"",$xml_text);
		$xml_text = str_replace("encoding='gb2312'","encoding=\"utf-8\"",$xml_text);
		$xml_text = iconv("GBK","UTF-8//IGNORE",$xml_text);
	}

	DAO_Log::debug("input xml:".$xml_text);
	//$xml = simplexml_load_string($xml_text);
	$dom = new domDocument;
	try
	{
		set_error_handler('handle_xml_error');
		$dom->loadXML($xml_text);
		restore_error_handler();
	}
	catch(DOMException $e)
	{
		restore_error_handler();
		$msg= 'load xml fail:'.$e->getMessage().CRLF.$xml_text;
		DAO_Log::debug('xml parse error:'.$msg);
		if(isset($dom))
		{
			unset($dom);
		}
		return -1;
	}
	$pack->format = 'XML';
	$root_tag_name=$dom->documentElement->tagName;
	DAO_Log::debug("rootTagName=$root_tag_name");
	$element_node;
	if(strstr($root_tag_name,'Envelope')||strstr($root_tag_name,'SOAP-ENV'))
	{
		DAO_Log::debug('input xml is soap');
		$pack->format = 'SOAP';
		//是soap消息
		//获取body
		$node = $dom->getElementsByTagName('Body')->item(0);
		if(!isset($node))
		{
			$msg = 'SOAP Body NOT Found';
			return -1;
		}
		$child;
		foreach($node->childNodes as $sub_item)
		{

			$len =  strlen(trim($sub_item->nodeValue));
			if($len)
			{
				$child = $sub_item;
				break;

			}
		}
		if(!isset($child))
		{
			$msg = 'SOAP Element within Body NOT Found';
			return -1;

		}
		$pack->type=$child->nodeName;
		if(strlen(trim($pack->type))==0)
		{
			$msg='SOAP Element withind Body has a EMPTY name';
			return -1;
		}
		$root_tag_name = $child->nodeName;
		$element_node = $child;
	}
	else
	{
		DAO_Log::debug('input xml is plainxml');
		$element_node = $dom;
	}

	//通过simplexml进行子节点遍历
	$splitter="\n";
	$escapeChar="\\n";
	$xml = simplexml_import_dom ($element_node);
	$pack->type = $xml->getName();
	DAO_Log::debug('the element type='.$pack->type);
	$style='std';
	$charset='UTF-8';
	foreach ( $xml as $tag=>$value )
	{
		//heade节点
		if($tag=='header')
		{
			foreach ($value as $key=>$text)
			{
				DAO_Log::debug( "header: $key=>$text\r\n");
				$pack->header[$key] = $text.'';
				if($key=='style')$style=$text;
			}
		}

		/*----------------------------------
		std style parse
		-------------------------------------*/
		if($style=='std')
		{
			if($tag=='field')
			{
				foreach($value as $key=>$text)
				{
					DAO_Log::debug("$key=>$text");
					$pack->field[]=$text.'';
				}
			}//---------------

			if($tag=='data')
			{
				//表记录节点
				if($style=='std')
				{
					$data=NULL;
					foreach($value as $key=>$text)
					{
						DAO_Log::debug("$key=>$text");
						$data[$key]=$text.'';
					}
				}
				if(isset($data) )
				{
					//增加表记录节点
					$pack->data[]=$data;
				}
			}//-------------
		}
		/*--------------std parse end---------------------------------------*/

		/*----------------------------------
		compact style parse
		-------------------------------------*/
		if($style=='compact')
		{
			if($tag=='field')
			{
				$pack->field = explode($splitter,trim($value));
			}
			if($tag=='data')
			{
				$dataArray = explode($splitter,$value);
				$data=null;
				foreach($dataArray as $dk =>$dv)
				{
					$fname = $pack->field[$dk];
					if(strlen($fname)==0)$fname =$dk;
					DAO_Log::debug("$fname=>$dv");
					$data[$fname] = resumeCrlf($dv);
				}
				if(isset($data))
				{
					$pack->data[]=$data;
				}
			}
		}
		/*--------------compact style parse end---------------------------------------*/
	}

	//这一段代码是因为php xml解析器只认utf-8,所以做的一些兼容
	//1 先记住外部要求的charset,因为有可能是GBK (来自ics)
	if($pack->header['charset'])
	{
		$pack->header['client_charset'] = $pack->header['charset'];
	}
	if($pack->header['encode'])
	{
		$pack->header['client_charset'] = $pack->header['encode'];
	}

	//2 强制设置为UTF-8，因为XML解析完的效果必然是UTF-8
	$pack->header['encode']='UTF-8';
	$pack->header['charset']='UTF-8';
	if(isset($dom))
	{
		unset($dom);
	}
	return 0;
}







function isEmptyXML($dataValue)
{
	if(!isset($dataValue))
	{
		return true;
	}
	if(is_string($dataValue))
	{
		if(strlen($dataValue)==0)
		{
			return true;
		}
	}
	return false;
}

/*
将QcsPackage对象输出为xml字符串
*/
function toXML(&$pack,$style="",$crlf=CRLF)
{

	//DAO_Log::debug(vexport($pack));
	if(strlen($style)==0)
	{
		$style = $pack->getHeader("style");
	}
	if($style=="compact")
	{
		$xml =  toXML_compact($pack,"\n",$style);
	}else
	{
		$xml =  toXML_std($pack,$crlf);
	}
	return $xml;
}

function toXML_std(&$pack,$crlf=CRLF)
{
	$data_encode = $pack->header["data_encode"];
	$encoding = $pack->header["encode"];

	//type为根节点
	$xml = "<".$pack->type.">".$crlf;
	//输出值如 "retcode" "reason"
	$tagHeader = QcsPackage::$TAG_HEADER;
	$xml.="<$tagHeader>$crlf";
	foreach($pack->header as $dataKey=>$dataValue)
	{
		if(isEmptyXML($dataValue))continue;
		$tag=$dataKey;
		$xml.="<".$tag.">";
		$xml.=$dataValue;
		$xml.="</".$tag.">".$crlf;
	}
	$xml.="</$tagHeader>$crlf";
	//输出表，遍历表里所有的data行
	foreach($pack->data as $key=>$value)
	{
		$tagData = QcsPackage::$TAG_DATA;
		$xml.="<$tagData>".$crlf;
		//再输出表
		$i=0;
		foreach($value as $dataKey=>$dataValue)
		{
			++$i;
			if(isEmptyXML($dataValue))continue;
			$tag=$dataKey;
			$xml.="<".$tag.">";
			$xml.=$dataValue;
			$xml.="</".$tag.">".$crlf;
		}
		$xml.="</$tagData>".$crlf;
	}

	$xml.="</".$pack->type.">";
	return $xml;
}



function toXML_compact(&$pack,$crlf=CRLF)
{
	//type为根节点
	$splitter ="\n";
	$escapeChar="\\n";
	$xml = "<".$pack->type.">".$crlf;
	//输出值如 "retcode" "reason"
	$tagHeader = QcsPackage::$TAG_HEADER;
	$xml.="<$tagHeader>$crlf";
	foreach($pack->header as $dataKey=>$dataValue)
	{
		if(isEmptyXML($dataValue))continue;
		$tag=$dataKey;
		$xml.="<".$tag.">";
		$xml.=$dataValue;
		$xml.="</".$tag.">".$crlf;
	}
	$xml.="</$tagHeader>$crlf";
	//将数据的列名输出到xml
	if(true)
	{
		if(sizeof($pack->data[0])>0)
		{
			$i = 0;
			$tagField = QcsPackage::$TAG_FIELD;
			$xml.="<$tagField>";
			foreach($pack->data[0] as $key=>$value)
			{
				++$i;
				$xml.="$key$crlf";
			}
			$xml.="</$tagField>".$crlf;
		}
	}
	//输出表，遍历表里所有的data行
	foreach($pack->data as $key=>$value)
	{
		$tagData = QcsPackage::$TAG_DATA;
		$xml.="<$tagData>";
		$i=0;
		foreach($value as $dataKey=>$dataValue)
		{
			++$i;
			$xml.=escapeCrlf($dataValue);
			$xml.=$crlf;
		}
		$xml.="</$tagData>".$crlf;
	}
	$xml.="</".$pack->type.">";
	return $xml;

}

function toSoap(&$pack,$style="std",$crlf=CRLF)
{
	global $soap_ns;
	return  "<SOAP-ENV:Envelope ".$soap_ns.">\r\n<SOAP-ENV:Body>\r\n".toXML($pack,$style,$crlf)."\r\n</SOAP-ENV:Body>\r\n</SOAP-ENV:Envelope>";
}

if($argv)
{
	if($argv[1]=="ut_sp_char")
	{
		$str="中文问题";
		echo urlencode($str)."\r\n";
		echo urldecode($str)."\r\n";
		DAO_Log::setMax();
		$str = file_get_contents("1.xml");
		echo $str;
		echo "\r\n";
		echo "---str2----\r\n";
		var_dump( iconv_get_encoding ("all"));
		$str2 = file_get_contents("2.xml");
		$str2 = iconv("ISO-8859-1","UTF-8",$str2)."<\r\n";
		echo  $str2 ."\r\n";
		echo "---str2----\r\n";


		$xml = simplexml_load_string($str);
		var_dump($xml);
		echo "\r\n";
		echo iconv("UTF-8","GBK",$xml->key2)."<\r\n";
		echo iconv("UTF-8","GBK",$xml->key)."<\r\n";
	}
	if($argv[1]=="ut_from_xml")
	{


		DAO_Log::setMax();
		$spstr = file_get_contents("spstr.txt");
		$str = file_get_contents("task_create_utf8_compact.xml");
		$spstr = urlencode($spstr);
		dao_str_replace("[var.request]",$spstr,$str);
		echo $str."\r\n\n\n\n\n\n\n";
		$pack = new QcsPackage();
		fromXML($pack,$str,$msg);
		var_dump($pack);
		echo ">>".$pack->header["encode"]."\r\n";
		echo ">>".$pack->data[0]["f_task_id"]."\r\n";
		echo ">>".$pack->data[0]["f_reply_content"]."\r\n";

		$xml = toXML($pack);



		echo "---------->\r\n $xml     \r\n-------------\r\n";


		$pack = new QcsPackage();
		fromXML($pack,$xml);
		$pack->decode();
		var_dump($pack);

	}
	if($argv[1]=="ut_xml_compact")
	{
		DAO_Log::setMax();

		$pack = new QcsPackage();

		$pack->header["encode"]="gbk";
		$pack->header["style"]="compact";
		$data["name"]="testname";
		$data["id"]="1234";
		$data["memo"]="line1\r\nline2";
		$pack->data[]=$data;
		$data["name"]="test";
		$data["id"]="1234";
		$data["memo"]=iconv("GBK","UTF-8","测试消息\n测试xml compact类型");
		$pack->data[]=$data;
		$pack->setEncode("UTF-8");
		$xmlstr = toXML($pack);
		echo "$xmlstr\r\n----------------\r\n";



		$pack = new QcsPackage();
		fromXML($pack,$xmlstr);

		var_dump($pack);

	}
	if($argv[1]=="ut_encode")
	{
		$str= "4663%3A%B9%E9%B5%B5%B2%D9%D7%F7";
		echo urldecode($str."\r\n");
		echo iconv("UTF-8","GBK",urldecode($str))."\r\n";
	}
}

?>
